#ifndef RX203_PTCL_PARSOR_H
#define RX203_PTCL_PARSOR_H

#include "parsorbase.h"
#include "udpreceivor.h"

// qthread
#include <QThread>
#include <QWaitCondition>
#include <QMutex>


#include <QVector>
#include <QList>

#define GET_OFFSET(TYPE, MEMBER) ((size_t)(&(((TYPE*)NULL)->MEMBER)))

#include <inttypes.h>
#include <endian.h>
/* 根据申工软件，实际发包制定 */
#pragma pack(push,1)
#define GAMMA_LEN 256

//size 779
typedef struct
{
    uint16_t w;
    uint16_t h;
    uint16_t port_num;
    uint8_t reserve0_1;
    uint16_t reserve0_2;
    uint8_t gamma[GAMMA_LEN];
    uint8_t reserve0_3[512];
    uint16_t reserve0_4;
}Pkt_ParHead;

#define RX203_DISPLAY_CMD ((uint8_t)0x30)
#define RX203_DISPLAY_PKT_LEN 779
#define RX203_DISPLAY_PKT_RGB_LEN 768
#define RX203_PORT_NUM 8

typedef struct
{
    uint8_t cmd;
    uint8_t ctrl_num;
#if __BYTE_ORDER == __LITTLE_ENDIAN
    uint8_t bit_port_no:4;
    uint8_t bit_pack_no:4;
#elif __BYTE_ORDER == __BIG_ENDIAN
    uint8_t bit_pack_no:4;
    uint8_t bit_port_no:4;
#else
#error "unknown endianess!"
#endif
    uint16_t led_num;
    uint8_t led_type;
    uint16_t reserve0_1;
    uint8_t reserve0_2;
    uint8_t rgb_data[RX203_DISPLAY_PKT_RGB_LEN];
    uint16_t reserve0_3;
}Pkt_Display;
#pragma pack(pop)

typedef struct
{
    //bool used;
    QByteArray* addr;
}PortPar;

typedef struct
{
    bool port_x_get[4];
} PortFlag;

typedef struct
{
    QMutex mutex;
//    QWaitCondition cond;
//    bool get_sync_frame;
    int wokers_number;
//    int idle_wokers_number;
    int idle_workers_number;
    QList<QByteArray*>* input_pkt_display_list;
} FrameOfPkt;


typedef enum {
    RX203_ERR_CODE_OK = 0,
    RX203_ERR_CODE_PAR_FILE_ERR = -1
}RX203_ERR_CODE;



class ParseWorker : public QObject
{
    Q_OBJECT

public:
    explicit ParseWorker(QImage* image, QVector<QVector<PortPar*>*>* p_par_vec,
                         QObject* parent = 0);
    ~ParseWorker();
    void taskStart() {flag_run = true;}
    void taskStop() {flag_run = false;}
    bool taskIsRun() {return flag_run;}

    void setCurrentTask(FrameOfPkt* current_task) {this->current_task = current_task;}

    int parse(QByteArray* display_pkt_data);
signals:
    void signal_frameComplete();

public slots:
    void parseThread();

private:
    bool flag_run;
    QImage* image;
    QVector<QVector<PortPar*>*>* p_par_vec;
    FrameOfPkt* current_task;
};

/* -------------------------------------------------------------------------------------------------------------- */
typedef struct
{
    ParseWorker* worker;
    QThread* thread;
} WorkerNode;


class RX203_PTCL_Parsor : public ParsorBase
{
    Q_OBJECT
public:
    RX203_PTCL_Parsor(QString par_file_path, int workers_num, QObject *p = 0);
    ~RX203_PTCL_Parsor();

    void addRawPkt(QByteArray& raw_data);

    //放入图像 的 buffer

signals:
    void signal_frameready();

private slots:
    void slot_getFrameCompelet();


private:
    inline int getPortId(uint8_t v);


    //造型
    int setParFile();
    void clearParFile();
    QString par_file_path;
    QVector<QVector<PortPar*>*> par_vec;

    //udp接收,
    void taskListInit();
    void taskListDeinit();
    void setWorkerTaskList(int index);
    FrameOfPkt* udp_recv_frame;

    //由于 上位机 只发 1 ~ 4 端口循环，这里做一下判断
    //收到同步帧 清空
    QMutex port_flag_vec_mutex;
    QVector<PortFlag*> port_flag_vec;
    void portFlagInit();
    void portFlagclear();
    void portFlagDeinit();


    //parsor 线程取的任务队列
    QMutex task_list_mutex;
//    QWaitCondition task_list_cond;
    bool task_busy;
    QList<FrameOfPkt*> task_list;    //2 个

    //parse 线程控制
    void threadSetInit();
    void threadStart();
    void threadAllStart();
    void threadStop();
    void threadAllStop();
    void threadSetDeinit();
    int workers_num;
    QVector<WorkerNode*> workerNodes_vec;

};

#endif // RX203_PTCL_PARSOR_H
